import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.RenderingHints;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;

import javax.swing.JPanel;


@SuppressWarnings("serial")
public class HexTileBoardView extends JPanel implements ComponentListener, ObservableModel.ModelChangeListener {
    private static final int DEFAULT_STROKE = 3;
    private static final int HIGHLIGHT_STROKE = 5;
    
    private DrawableTileBoard mBoard;
    private DrawableTileBoard mOverlayBoard;
    
    private Polygon mHexagon;
    
    private double mCenterX;
    private double mCenterY;
    private double mHexWidth;
    private double mHexHeight;
    private double mHexSide;
    private double mHexRadius;
    private double mDx;
    private double mDy;
    
    public HexTileBoardView(DrawableTileBoard board, DrawableTileBoard overlay) {
        mBoard = board;
        mOverlayBoard = overlay;
        addComponentListener(this);
    }
    
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        if(mHexagon != null) {
            Graphics2D g2 = (Graphics2D) g;
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                    RenderingHints.VALUE_ANTIALIAS_ON);
            
            g2.setStroke(new BasicStroke(DEFAULT_STROKE));
            for(int[] coords : mBoard.getAvailableCoordinates()) {
                drawTile(g2, mBoard.getDrawableTile(coords), coords, mBoard.getBorderColor());
            }
            
            g2.setStroke(new BasicStroke(HIGHLIGHT_STROKE));
            for(int[] overlayCoords : mOverlayBoard.getAvailableCoordinates()) {
                DrawableTile tile = mOverlayBoard.getDrawableTile(overlayCoords);
                if(tile != null) {
                    drawTile(g2, mOverlayBoard.getDrawableTile(overlayCoords), overlayCoords, 
                            mOverlayBoard.getBorderColor());
                }
            }
        }
    }
    
    private void drawTile(Graphics2D g2, DrawableTile tile, int[] coords, Color borderColor) {
        Color tileColor = null;
        if(tile != null) {
            tileColor = tile.getTileColor();
        }
        
        drawHexagon(g2, coords, tileColor, borderColor);
    }
    
    private void drawHexagon(Graphics2D g2, int[] coords, Color tileColor, Color borderColor) {
        int q = coords[0];
        int r = coords[1];
        int deltaX = (int) ((q * mHexWidth) + ((mDx / 2) * r));
        int deltaY = (int) (r * mDy);
        
        mHexagon.translate(deltaX, deltaY);
        
        if(tileColor != null) {
            g2.setColor(tileColor);
            g2.fillPolygon(mHexagon);
        }
        if(borderColor != null) {
            g2.setColor(borderColor);
            g2.drawPolygon(mHexagon);
        }
        
        mHexagon.translate(-deltaX, -deltaY);
    }

    public void componentHidden(ComponentEvent arg0) {
    }

    public void componentMoved(ComponentEvent arg0) {
    }

    public void componentResized(ComponentEvent arg0) {
        initSize();
    }

    public void componentShown(ComponentEvent arg0) {
        initSize();
    }
    
    private void initSize() {
        int width = getWidth();
        int height = getHeight();
        mHexWidth = width / 18.0;
        mHexSide = mHexWidth / (2 * Math.cos(Math.PI / 6));
        mHexRadius = mHexSide / (2 * Math.sin(Math.PI / 6));
        mHexHeight = 2 * mHexSide;
        
        mDy = (3 * mHexSide) / 2;
        mDx = mHexWidth;
        mCenterX = width / 2;
        mCenterY = height / 2;
        
        mHexagon = new Polygon();
        for(int q = 0; q < 6; q++) {
            double radians = ((q * 60) + 30) * Math.PI / 180;
            mHexagon.addPoint((int) (mCenterX + mHexRadius * Math.cos(radians)), 
                    (int) (mCenterY + mHexRadius * Math.sin(radians)));
        }
        
        repaint();
    }

    @Override
    public void onModelChange(ObservableModel model) {
        repaint();
    }
}
